﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NetworkAnalysis
{
    class NATools
    {
        private static string roadsPersonCountResFilePath = @"";

        #region/-----------------------------------获取网络数据集（网络数据集已创建时使用）---------------------------------------/
        public static INetworkDataset getNetworkDataset(string gdbDatasetDirectoryPath, string netWorkDatasetName)
        {
            string[] gdbFilePaths = gdbDatasetDirectoryPath.Split('\\');
            string gdbWorkSpacePath = null;
            string gdbDataSetPath = null;

            for (int i = 0; i < gdbFilePaths.Length - 2; i++)
            {
                gdbWorkSpacePath += gdbFilePaths[i] + "\\";
            }
            gdbWorkSpacePath += gdbFilePaths[gdbFilePaths.Length - 2];

            gdbDataSetPath = gdbFilePaths[gdbFilePaths.Length - 1];

            IWorkspaceFactory pWSF = new FileGDBWorkspaceFactoryClass();
            IFeatureWorkspace pFWS = pWSF.OpenFromFile(gdbWorkSpacePath, 0) as IFeatureWorkspace;
            IFeatureDataset pFeatureDataset = pFWS.OpenFeatureDataset(gdbDataSetPath);

            IFeatureDatasetExtensionContainer pFeatureDatasetExContainer = pFeatureDataset as IFeatureDatasetExtensionContainer;
            IFeatureDatasetExtension pFeatureDatasetEx = pFeatureDatasetExContainer.FindExtension(esriDatasetType.esriDTNetworkDataset);
            IDatasetContainer3 pDatasetContainer3 = pFeatureDatasetEx as IDatasetContainer3;

            if (pDatasetContainer3 != null)
            {
                IDataset pDataset = pDatasetContainer3.get_DatasetByName(esriDatasetType.esriDTNetworkDataset, netWorkDatasetName);
                return pDataset as INetworkDataset;
            }
            INASolver pNASolver = new NARouteSolverClass();
            INASolverSettings2 pNASolverSettings2 = pNASolver as INASolverSettings2;

            return null;
        }
        #endregion

        #region/-----------------------------------创建网络分析环境(路径分析环境)---------------------------------------/
        public static INAContext createNAContext_Route(string contextName, INetworkDataset pNetworkDataset)
        {
            INASolver pNASolver = new NARouteSolverClass(); //创建一个网路分析（最短路径分析）解决器
            INASolverSettings pNASolverSettings = pNASolver as INASolverSettings;

            //利用网络分析数据集(INetworkDataset)和网络分析解决器(INASolver)创建网络分析环境(INAContext)
            //1. 获取网络数据集的元素（边、交汇点、转向）
            //2. 创建网络分析环境并且绑定网络数据集
            IDatasetComponent pDatasetComponent = pNetworkDataset as IDatasetComponent;
            IDENetworkDataset pDENetworkDataset = pDatasetComponent.DataElement as IDENetworkDataset;

            INAContext pNAContext = null;
            pNAContext = pNASolver.CreateContext(pDENetworkDataset, contextName);
            INAContextEdit pNAContextEdit = pNAContext as INAContextEdit;
            pNAContextEdit.Bind(pNetworkDataset, new GPMessagesClass()); //GPMessage表示地理处理任务执行期间的信息。包括：何时开始处理，什么参数值被使用，任务进度等

            //设置网络属性
            if (!pNAContext.Solver.CanAccumulateAttributes)
            {
                INARouteSolver pNARouteSolver = pNASolver as INARouteSolver;
                pNARouteSolver.FindBestSequence = true;
                pNARouteSolver.PreserveFirstStop = true;
                pNARouteSolver.PreserveLastStop = true;
                pNARouteSolver.UseTimeWindows = false;
                pNARouteSolver.OutputLines = esriNAOutputLineType.esriNAOutputLineTrueShapeWithMeasure;

                pNASolver.UpdateContext(pNAContext, pDENetworkDataset, new GPMessagesClass());
            }
            return pNAContext;
        }
        #endregion

        #region/-----------------------------------进行网络分析（最短路径分析）---------------------------------------/
        public static List<NAResult> createRoute2(INAContext pNAContext, string SettleTxtFileName, string WorkTxtFileName)
        {
            List<string> settlePIDList = new List<string>();
            List<string> workPIDList = new List<string>();
            List<IGeometry> pSettleGeoList = new List<IGeometry>();
            List<IGeometry> pWorkGeoList = new List<IGeometry>();
            List<NAResult> naResultList = new List<NAResult>();

            System.IO.FileStream SettleTxtStream = File.OpenRead(SettleTxtFileName);
            StreamReader settleStreamReader = new StreamReader(SettleTxtStream, Encoding.GetEncoding("GBK"));
            string settleInfoStrLine = null;
            while ((settleInfoStrLine = settleStreamReader.ReadLine()) != null)
            {
                string[] settleStrInfo = settleInfoStrLine.Split('|');
                settlePIDList.Add(settleStrInfo[1]);
                string[] settlePtsInfo = settleStrInfo[2].Split(',');
                IPoint settlePts = new PointClass();
                settlePts.PutCoords(Convert.ToDouble(settlePtsInfo[0]), Convert.ToDouble(settlePtsInfo[1]));
                pSettleGeoList.Add(settlePts);
            }
            settleStreamReader.Close();
            SettleTxtStream.Close();

            System.IO.FileStream WorkTxtStream = File.OpenRead(WorkTxtFileName);
            StreamReader workStreamReader = new StreamReader(WorkTxtStream, Encoding.GetEncoding("GBK"));
            string workInfoStrLine = null;
            while ((workInfoStrLine = workStreamReader.ReadLine()) != null)
            {
                string[] workStrInfo = workInfoStrLine.Split('|');
                workPIDList.Add(workStrInfo[1]);
                string[] workPtsInfo = workStrInfo[2].Split(',');
                IPoint workPts = new PointClass();
                workPts.PutCoords(Convert.ToDouble(workPtsInfo[0]), Convert.ToDouble(workPtsInfo[1]));
                pWorkGeoList.Add(workPts);
            }
            workStreamReader.Close();
            WorkTxtStream.Close();

            INamedSet pNamedSet = pNAContext.NAClasses;

            INAClass pStopsNAClass = pNamedSet.get_ItemByName("Stops") as INAClass;
            IFeatureClass pStopsFeatureClass = pStopsNAClass as IFeatureClass;

            IFeature pStopsFeature = null;
            //这里需要给stopsFeatureClass中的这3个属性赋值
            int nameFieldIndex = 0;
            int statusFieldIndex = 0;
            int sequenceFieldIndex = 0;

            INALocator2 pNALocator_2 = pNAContext.Locator as INALocator2;
            IPoint pStartOriginInputPt = null;
            IPoint pStartRoadOutputPt = null;
            INALocation pStartNALocation = null;
            double pStartDistanceToLocation = 5000;
            INALocationObject pStartNALocationObj = null;

            IPoint pEndOriginInputPt = null;
            IPoint pEndRoadOutputPt = null;
            INALocation pEndNALocation = null;
            double pEndDistanceToLocation = 5000;
            INALocationObject pEndNALocationObj = null;

            for (int i = 0; i < pSettleGeoList.Count; i++)
            {
                List<string> roadIDList = new List<string>();
                double routeLength = 0.0;
                ClearBeforeAnalysis(pNAContext);

                //创建Stops(Settle)要素
                pStopsFeature = pStopsFeatureClass.CreateFeature();
                pStopsFeature.Shape = pSettleGeoList[i];

                pStartOriginInputPt = pSettleGeoList[i] as IPoint;
                pStartRoadOutputPt = new PointClass();
                pStartNALocation = new NALocationClass();
                pNALocator_2.QueryLocationByPoint(pStartOriginInputPt, ref pStartNALocation, ref pStartRoadOutputPt, ref pStartDistanceToLocation);
                if (pStartRoadOutputPt == null)
                {
                    pStartRoadOutputPt = pStartOriginInputPt;
                }

                //设置Stops的NALocation
                pStartNALocationObj = pStopsFeature as INALocationObject;
                pStartNALocationObj.NALocation = pStartNALocation;

                //设置关键字段属性值
                nameFieldIndex = pStopsFeatureClass.FindField("Name");
                statusFieldIndex = pStopsFeatureClass.FindField("Status");
                sequenceFieldIndex = pStopsFeatureClass.FindField("Sequence");
                pStopsFeature.set_Value(nameFieldIndex, "SettlePts" + "_" + i.ToString());
                pStopsFeature.set_Value(statusFieldIndex, esriNAObjectStatus.esriNAObjectStatusOK);
                pStopsFeature.set_Value(sequenceFieldIndex, 1);
                pStopsFeature.Store();

                //创建Stops(Work)要素
                pStopsFeature = pStopsFeatureClass.CreateFeature();
                pStopsFeature.Shape = pWorkGeoList[i];

                pEndOriginInputPt = pWorkGeoList[i] as IPoint;
                pEndRoadOutputPt = new PointClass();
                pEndNALocation = new NALocationClass();
                pNALocator_2.QueryLocationByPoint(pEndOriginInputPt, ref pEndNALocation, ref pEndRoadOutputPt, ref pEndDistanceToLocation);
                if (pEndRoadOutputPt == null)
                {
                    pEndRoadOutputPt = pEndOriginInputPt;
                }

                //设置Stops的NALocation
                pEndNALocationObj = pStopsFeature as INALocationObject;
                pEndNALocationObj.NALocation = pEndNALocation;

                //设置关键字段属性值
                nameFieldIndex = pStopsFeatureClass.FindField("Name");
                statusFieldIndex = pStopsFeatureClass.FindField("Status");
                sequenceFieldIndex = pStopsFeatureClass.FindField("Sequence");
                pStopsFeature.set_Value(nameFieldIndex, "WorkPts" + "_" + i.ToString());
                pStopsFeature.set_Value(statusFieldIndex, esriNAObjectStatus.esriNAObjectStatusOK);
                pStopsFeature.set_Value(sequenceFieldIndex, 2);
                pStopsFeature.Store();

                try
                {
                    INASolver pNASolver = pNAContext.Solver;
                    pNASolver.Solve(pNAContext, new GPMessagesClass(), new CancelTrackerClass());
                }
                catch (Exception e)
                {
                    Console.WriteLine("已计算" + (i + 1).ToString() + "条路径");
                    continue;
                }

                INAResult pNAResult = pNAContext.Result;
                INATraversalResultQuery2 pNATraversalResultQuery2 = pNAResult as INATraversalResultQuery2;
                IFeatureClass pEdgeFeatureClass = pNATraversalResultQuery2.FeatureClass[esriNetworkElementType.esriNETEdge];

                IFeatureCursor pEdgeFeatureCursor = pEdgeFeatureClass.Search(null, false);
                IFeature pEgdeFeature = pEdgeFeatureCursor.NextFeature();

                while (pEgdeFeature != null)
                {
                    INATraversalResultElement pNATraversalResElement = pEgdeFeature as INATraversalResultElement;
                    roadIDList.Add(pNATraversalResElement.SourceOID.ToString());
                    pEgdeFeature = pEdgeFeatureCursor.NextFeature();
                }

                //保存结果路径Route, 并获取总路径长度
                INAClass pNARoutesClass = pNamedSet.get_ItemByName("Routes") as INAClass;
                IFeatureClass pRoutesFeatureClass = pNARoutesClass as IFeatureClass;
                IFeatureCursor pRoutesFeatureCursor = pRoutesFeatureClass.Search(null, false);
                IFeature pRoutesFeature = pRoutesFeatureCursor.NextFeature();
                while (pRoutesFeature != null)
                {
                    routeLength = Convert.ToDouble(pRoutesFeature.get_Value(pRoutesFeature.Fields.FindField("Total_Length")));
                    pRoutesFeature = pRoutesFeatureCursor.NextFeature();
                }


                NAResult naResult = new NAResult(i + 1, workPIDList[i], routeLength, pStartOriginInputPt, pEndOriginInputPt, pStartRoadOutputPt, pEndRoadOutputPt, roadIDList.ToArray());
                naResultList.Add(naResult);
                if ((i + 1) % 10 == 0)
                {
                    Console.WriteLine("已计算" + (i + 1).ToString() + "条路径");
                }
            }

            return naResultList;
        }

        private static void ClearBeforeAnalysis(INAContext pNAContext)
        {
            //删除stops 和 routes 这两个网络分析要素类
            IFeatureClass pFeatureClass = null;
            INAClass pNAClass = null;
            INamedSet pNameset = pNAContext.NAClasses;
            pFeatureClass = pNameset.get_ItemByName("Stops") as IFeatureClass;
            pNAClass = pFeatureClass as INAClass;
            pNAClass.DeleteAllRows();

            pFeatureClass = pNameset.get_ItemByName("Routes") as IFeatureClass;
            pNAClass = pFeatureClass as INAClass;
            pNAClass.DeleteAllRows();
        }

        #endregion

        #region/-----------------------------------写入数据到Txt文件---------------------------------------/
        public static void writeDataToTxt(string txtFileName, List<NAResult> naResult)
        {
            System.IO.FileStream fileStream = File.OpenWrite(txtFileName);

            StreamWriter streamWriter = new StreamWriter(fileStream, Encoding.GetEncoding("GBK"));

            string personNARecord = null;
            foreach (NAResult nar in naResult)
            {
                personNARecord = null;
                string id = nar.getId().ToString();
                string buildingID = nar.getpID();
                string routeLength = Math.Round(nar.getRouteLength(), 2).ToString();

                IPoint originStartPt = nar.getOriginStartPt();
                string originStartPt_X = originStartPt.X.ToString();
                string originStartPt_Y = originStartPt.Y.ToString();

                IPoint originEndPt = nar.getOriginEndPt();
                string originEndPt_X = originEndPt.X.ToString();
                string originEndPt_Y = originEndPt.Y.ToString();

                IPoint roadStartPt = nar.getRoadStartPt();
                string roadStartPt_X = roadStartPt.X.ToString();
                string roadStartPt_Y = roadStartPt.Y.ToString();

                IPoint roadEndPt = nar.getRoadEndPt();
                string roadEndPt_X = roadEndPt.X.ToString();
                string roadEndPt_Y = roadEndPt.Y.ToString();

                string roadID = null;
                List<string> roadIDList = new List<string>(nar.getRoadIDList());
                for (int i = 0; i < roadIDList.Count - 1; i++)
                {
                    roadID = roadID + roadIDList[i];
                    roadID = roadID + ",";
                }
                roadID = roadID + roadIDList[roadIDList.Count - 1];

                personNARecord = id + "|" + buildingID + "|" + routeLength + "|" + originStartPt_X + "|" + originStartPt_Y + "|" + originEndPt_X + "|" + originEndPt_Y + "|" + roadStartPt_X + "|" + roadStartPt_Y + "|" + roadEndPt_X + "|" + roadEndPt_Y + "|" + roadID;

                streamWriter.WriteLine(personNARecord);

                streamWriter.Flush();
            }

            streamWriter.Close();
            fileStream.Close();

        }
        #endregion

        #region/---------------------------------------------创建网络数据集（网络数据集未创建时使用）--------------------------------------------/
        //定义全局变量
        public static IDataset dataset;    //所构建的网络数据集
        public static string CostAttribute = null;   //网络分析的成本属性

        //NATools.createNetwork(NATools.workspaceName, "RoadDataset", "RoadNet_ND", "RoadNetWork", "FreeTime");  //引用实例
        //注：最后两个参数的名称是道路网矢量数据的名称，以及路网权重的属性名称
        public static IFeatureDataset createNetwork(string workspaceName, string featureDatasetName, string NDName, string edgeNetworkSourceName, string netFieldEvalName)
        {
            ////// Creating a network dataset data element //////

            // Create an empty data element for a buildable network dataset.
            IDENetworkDataset2 deNetworkDataset = new DENetworkDatasetClass();
            deNetworkDataset.Buildable = true;

            // Open the feature dataset and cast to the IGeoDataset interface.
            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
            IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);
            IFeatureWorkspace pFeatureWorkspace = workspaceFactory.OpenFromFile(workspaceName, 0) as IFeatureWorkspace;
            IFeatureDataset pFeatureDataset = pFeatureWorkspace.OpenFeatureDataset(featureDatasetName);
            IGeoDataset geoDataset = (IGeoDataset)pFeatureDataset;

            // Copy the feature dataset's extent and spatial reference to the network dataset data element.
            IDEGeoDataset deGeoDataset = (IDEGeoDataset)deNetworkDataset;
            deGeoDataset.Extent = geoDataset.Extent;
            deGeoDataset.SpatialReference = geoDataset.SpatialReference;

            // Specify the name of the network dataset.
            IDataElement dataElement = (IDataElement)deNetworkDataset;
            dataElement.Name = NDName;

            ////// Adding network sources //////
            // Specify the network dataset's elevation model.
            deNetworkDataset.ElevationModel = esriNetworkElevationModel.esriNEMNone;

            // Specifying the turn source
            deNetworkDataset.SupportsTurns = true;

            // Create an EdgeFeatureSource object and point it to the Streets feature class. ?
            INetworkSource edgeNetworkSource = new EdgeFeatureSourceClass();
            edgeNetworkSource.Name = edgeNetworkSourceName;
            edgeNetworkSource.ElementType = esriNetworkElementType.esriNETEdge;

            // Set the edge feature source's connectivity settings.
            IEdgeFeatureSource edgeFeatureSource = (IEdgeFeatureSource)edgeNetworkSource;
            edgeFeatureSource.UsesSubtypes = false;
            edgeFeatureSource.ClassConnectivityGroup = 1;
            edgeFeatureSource.ClassConnectivityPolicy = esriNetworkEdgeConnectivityPolicy.esriNECPEndVertex;


            // Create a StreetNameFields object and populate its settings.
            IStreetNameFields streetNameFields = new StreetNameFieldsClass();
            streetNameFields.Priority = 1;     // Priority 1 indicates the primary street name.
            streetNameFields.StreetNameFieldName = "ROADID";

            // Add the StreetNameFields object to a new NetworkSourceDirections object,
            // then add it to the EdgeFeatureSource created earlier.
            INetworkSourceDirections nsDirections = new NetworkSourceDirectionsClass();
            IArray nsdArray = new ArrayClass();
            nsdArray.Add(streetNameFields);
            nsDirections.StreetNameFields = nsdArray;
            edgeNetworkSource.NetworkSourceDirections = nsDirections;

            // Create a NetworkDirections object and populate its settings.
            INetworkDirections networkDirections = new NetworkDirectionsClass();
            networkDirections.DefaultOutputLengthUnits = esriNetworkAttributeUnits.esriNAUMeters;
            //networkDirections.TimeAttributeName = "DriveTime"; //添加了driveTime的属性字段
            //networkDirections.LengthAttributeName = "Meters";


            // Add the NetworkDirections object to the network dataset data element.
            deNetworkDataset.Directions = networkDirections;

            IArray sourceArray = new ArrayClass();
            sourceArray.Add(edgeNetworkSource);

            deNetworkDataset.Sources = sourceArray;

            ////// Adding network attributes //////
            IArray attributeArray = new ArrayClass();

            // Initialize variables reused when creating attributes:
            IEvaluatedNetworkAttribute evalNetAttr;
            INetworkAttribute2 netAttr2;
            INetworkFieldEvaluator netFieldEval;
            INetworkConstantEvaluator netConstEval;

            // Create an EvaluatedNetworkAttribute object and populate its settings.
            evalNetAttr = new EvaluatedNetworkAttributeClass();
            netAttr2 = (INetworkAttribute2)evalNetAttr;
            netAttr2.Name = "DriveTime";
            netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
            netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
            netAttr2.Units = esriNetworkAttributeUnits.esriNAUSeconds;
            netAttr2.UseByDefault = true;

            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("[" + netFieldEvalName + "]", "");
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized,
                (INetworkEvaluator)netFieldEval);

            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("[" + netFieldEvalName + "]", "");
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized,
                (INetworkEvaluator)netFieldEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

            // Add the attribute to the array.
            attributeArray.Add(evalNetAttr);

            // Add the attribute to the NetworkDataset
            deNetworkDataset.Attributes = attributeArray;

            ////// Creating and building the network dataset //////
            // Get the feature dataset extension and create the network dataset based on the data element.
            IFeatureDatasetExtensionContainer fdxContainer = (IFeatureDatasetExtensionContainer)pFeatureDataset;
            IFeatureDatasetExtension fdExtension = fdxContainer.FindExtension(esriDatasetType.esriDTNetworkDataset);
            IDatasetContainer2 datasetContainer2 = (IDatasetContainer2)fdExtension;
            IDEDataset deDataset = (IDEDataset)deNetworkDataset;
            INetworkDataset networkDataset = (INetworkDataset)datasetContainer2.CreateDataset(deDataset);
            // Once the network dataset is created, build it.
            INetworkBuild networkBuild = (INetworkBuild)networkDataset;
            networkBuild.BuildNetwork(geoDataset.Extent);

            return pFeatureDataset;
        }
        #endregion

        #region/---------------------------------------------打开与删除网络数据集--------------------------------------------/
        public static void deleteNetwork()
        {
            dataset.Delete();
        }

        public static INetworkDataset openNetwork(IFeatureDataset pFeatureDataset)
        {
            // 打开网络
            IFeatureDatasetExtensionContainer featureDatasetExtensionContainer = pFeatureDataset as IFeatureDatasetExtensionContainer;
            IFeatureDatasetExtension featureDatasetExtension = featureDatasetExtensionContainer.FindExtension(esriDatasetType.esriDTNetworkDataset);
            IDatasetContainer3 datasetContainer3 = featureDatasetExtension as IDatasetContainer3;

            // 加载网络数据集
            INetworkDataset networkDataset;
            IEnumDataset enumDataset;
            enumDataset = datasetContainer3.get_Datasets(esriDatasetType.esriDTNetworkDataset) as IEnumDataset;
            if (enumDataset == null)
            {
                Console.WriteLine("不存在网络数据集");
                return;
            }
            enumDataset.Reset();
            dataset = enumDataset.Next();
            if (dataset != null)
            {
                // 打开要素数据集中的网络数据集
                dataset = datasetContainer3.get_DatasetByName(esriDatasetType.esriDTNetworkDataset, dataset.Name);
                networkDataset = dataset as INetworkDataset;

                // 获取成本属性和限制属性
                INetworkAttribute networkAttribute;
                //networkDataset.AttributeCount+
                for (int i = 0; i < networkDataset.AttributeCount; i++)
                {
                    networkAttribute = networkDataset.get_Attribute(i);
                    if (networkAttribute.UsageType == esriNetworkAttributeUsageType.esriNAUTCost)
                    {
                        CostAttribute = networkAttribute.Name;
                    }
                }
            }
            return networkDataset;
        }
        #endregion

        #region/---------------------------------------------居民出行路径重构---------------------------------------------------/
        public static const int LINK_NUM = 29406;
        public static void reconstructNARoutes(string rawPersonResultFilePath, string ReconstructPersonResultFilePath, IFeatureClass pFeatureClass)
        //pFeatureClass为双向路网
        {
            string[] rawPersonResultFiles = System.IO.Directory.GetFiles(rawPersonResultFilePath);
            foreach (string entireFileName in rawPersonResultFiles)
            {
                string fileName = System.IO.Path.GetFileName(entireFileName);
                System.IO.FileStream fileStream = System.IO.File.OpenRead(entireFileName);
                System.IO.StreamReader streamReader = new StreamReader(fileStream);
                string newNAResultFileName = ReconstructPersonResultFilePath + fileName;
                System.IO.FileStream fileStream_1 = System.IO.File.OpenWrite(newNAResultFileName);
                System.IO.StreamWriter streamWriter = new StreamWriter(fileStream_1);

                string naResStr = null;
                int recordCount = 0;
                while ((naResStr = streamReader.ReadLine()) != null)
                {
                    recordCount++;
                    string[] naResInfo = naResStr.Split('|');

                    List<string> roadIDList = new List<string>();
                    string[] roadIDArray = naResInfo[10].Split(',');
                    for (int i = 0; i < roadIDArray.Length - 1; i++)
                    {
                        string roadID = roadIDArray[i];
                        string nextRoadID = roadIDArray[i + 1];
                        int roadCode = Convert.ToInt32(roadID);
                        int nextRoadCode = Convert.ToInt32(nextRoadID);
                        if (nextRoadCode - roadCode == LINK_NUM || roadCode - nextRoadCode == LINK_NUM || roadCode == nextRoadCode)
                            continue;
                        roadIDList.Add(roadIDArray[i]);
                    }
                    roadIDList.Add(roadIDArray[roadIDArray.Length - 1]);

                    IQueryFilter pQueryFilter = new QueryFilterClass();
                    IPoint comparePt = new PointClass();

                    for (int i = 0; i < roadIDList.Count; i++)
                    {
                        pQueryFilter.WhereClause = "ROADID=" + "'" + roadIDList[i] + "'";
                        IFeatureCursor pFeatureCursor = pFeatureClass.Search(pQueryFilter, false);
                        IFeature pFeature = pFeatureCursor.NextFeature();
                        while (pFeature != null)
                        {
                            IPolyline pPolyline = pFeature.Shape as IPolyline;
                            IPoint fromPt = pPolyline.FromPoint;
                            IPoint toPt = pPolyline.ToPoint;
                            if (i == 0)
                            {
                                comparePt.PutCoords(toPt.X, toPt.Y);
                            }
                            else
                            {
                                if (comparePt.Compare(toPt) == 0)
                                {
                                    int roadCode = Convert.ToInt32(roadIDList[i]);
                                    if (roadCode <= LINK_NUM)
                                        roadCode = roadCode + LINK_NUM;
                                    else
                                        roadCode = roadCode - LINK_NUM;
                                    roadIDList[i] = roadIDList[i].Replace(roadIDList[i], roadCode.ToString());
                                    comparePt.PutCoords(fromPt.X, fromPt.Y);
                                    pFeature = pFeatureCursor.NextFeature();
                                    continue;
                                }
                                if (comparePt.Compare(fromPt) != 0 && comparePt.Compare(toPt) != 0)
                                {
                                    int roadCode = Convert.ToInt32(roadIDList[i - 1]);
                                    if (roadCode <= LINK_NUM)
                                        roadCode = roadCode + LINK_NUM;
                                    else
                                        roadCode = roadCode - LINK_NUM;
                                    roadIDList[i - 1] = roadIDList[i - 1].Replace(roadIDList[i - 1], roadCode.ToString());
                                }
                                comparePt.PutCoords(toPt.X, toPt.Y);
                            }
                            pFeature = pFeatureCursor.NextFeature();
                        }
                    }

                    string newNAResultStr = null;
                    for (int i = 0; i < naResInfo.Length - 1; i++)
                    {
                        newNAResultStr = newNAResultStr + naResInfo[i] + "|";
                    }
                    string roadIDListStr = null;
                    for (int i = 0; i < roadIDList.Count; i++)
                    {
                        if (i < roadIDList.Count - 1)
                            roadIDListStr = roadIDListStr + roadIDList[i] + ",";
                        else
                            roadIDListStr = roadIDListStr + roadIDList[i];
                    }
                    newNAResultStr = newNAResultStr + roadIDListStr;
                    streamWriter.WriteLine(newNAResultStr);
                    streamWriter.Flush();

                    if (recordCount % 100 == 0)
                    {
                        Console.WriteLine("已重构" + recordCount.ToString() + "条路径！");
                    }
                }
                streamWriter.Close();
                fileStream_1.Close();
                streamReader.Close();
                fileStream.Close();
                Console.WriteLine(fileName + "路径已重构!");
            }

        }
        #endregion
    }
}
